using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Xml;

namespace WMOSSExperts.PackageBuilder
{
    
    /// <summary>
    /// The base class of all solution items
    /// </summary>
    public abstract class BaseSolutionItem
    {
        public String FileName;
        public String SourcePath;
        public Boolean IsExcluded = false;

        /// <summary>
        /// The target location of the solution item
        /// </summary>
        private String _location;

        /// <summary>
        /// Gets or sets the target location of the solution item
        /// </summary>
        public virtual String Location
        {   
            get
            {
                if (String.IsNullOrEmpty(_location))
                {
                    Int32 pos = this.SourcePath.IndexOf(@"\12\Template\", StringComparison.InvariantCultureIgnoreCase);
                    if (pos < 0) throw new ArgumentOutOfRangeException("element", @"the full path doesn't contain \12\Template\");
                    _location = this.SourcePath.Substring(pos + 13);
                }
                return _location;
            }
            set{_location = value;}
        }

        /// <summary>
        /// Gets the XML node name of the solution item in the manifest file
        /// </summary>
        public abstract String XmlNodeName { get;}

        /// <summary>
        /// Gets the XML parent node name to stors the solution item in the manifest file
        /// </summary>
        public virtual string XmlParentNodeName
        {
            get { return this.XmlNodeName + "s"; }
        }
    

        /// <summary>
        /// Build the DDF line for this item
        /// </summary>
        /// <returns></returns>
        public virtual String BuildDDFLine()
        {
            return String.Format("\"{0}\" \"{1}\"", this.SourcePath, this.Location);
        }

        /// <summary>
        /// Adds the solution item in the xml manifest document
        /// </summary>
        /// <param name="doc"></param>
        public virtual void AddToManifest(XmlDocument doc)
        {
            XmlNamespaceManager mngr = new XmlNamespaceManager(doc.NameTable);
            mngr.AddNamespace("wss",PackageBuilder.WSSSchemaURI);
            XmlNode parentNode = doc.SelectSingleNode(String.Format("//wss:{0}", this.XmlParentNodeName),mngr);

            if (parentNode == null)
            {
                parentNode = doc.CreateNode(XmlNodeType.Element,this.XmlParentNodeName,PackageBuilder.WSSSchemaURI);
                doc.FirstChild.AppendChild(parentNode);
            }

            XmlNode solutionItemNode = doc.CreateNode(XmlNodeType.Element, this.XmlNodeName, PackageBuilder.WSSSchemaURI);
            parentNode.AppendChild(solutionItemNode);
            
            XmlAttribute locationAttribute = doc.CreateAttribute("Location");
            solutionItemNode.Attributes.Append(locationAttribute);
            locationAttribute.Value=this.Location;

            this.AddAditionalAttribute(doc, solutionItemNode);
        }

        /// <summary>
        /// Add additional attribute in the current solution item node when it is adding to the manifest file
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="solutionItemNode"></param>
        public virtual void AddAditionalAttribute(XmlDocument doc, XmlNode solutionItemNode)
        {
        }

        /// <summary>
        /// Gets the Solution item type based on this ManifestElementType value
        /// </summary>
        /// <param name="elementType"></param>
        /// <param name="element"></param>
        /// <returns></returns>
        public static BaseSolutionItem GetSolutionItem(ManifestElementType elementType, FileInfo element)
        {
            //Check the sourcePath length because makecab doesn't allow path growther than 256 characters 
            if (element.FullName.Length > 256)
                throw new ArgumentOutOfRangeException("element", "the source path is too long to be trated by makecab");

            BaseSolutionItem item = null;
            switch (elementType)
            {
                case ManifestElementType.Feature:
                    item = new FeatureItem();
                    break;
                case ManifestElementType.TemplateFile:
                    item=new TemplateItem();
                    break;
                case ManifestElementType.Assembly:
                    item = new AssemblyItem();
                    break;
                default:
                    item = new RootItem();
                    break;
            }

            item.FileName = element.Name;
            item.SourcePath = element.FullName;
            return item;
        }
        
    }

}
